package com.pancm.datacollector.processor.impl;

import com.pancm.datacollector.processor.DataProcessor;
import com.pancm.datacollector.processor.ProcessorConfig;
import com.pancm.datacollector.queue.CollectedData;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 使用 OGNL 表达式处理数据的处理器
 */
@Component
public class OgnlDataProcessor implements DataProcessor {
    private static final Logger LOG = LoggerFactory.getLogger(OgnlDataProcessor.class);

    private ProcessorConfig config;
    private Map<String, Object> ognlExpressions;

    @Value("${collector.processor.rulesPath:classpath:rules.txt}")
    private String rulesPath;

    public OgnlDataProcessor(ProcessorConfig config) {
        this.config = config;
        this.ognlExpressions = new HashMap<>();
    }

    public OgnlDataProcessor() {
        this.ognlExpressions = new HashMap<>();
    }

    @PostConstruct
    public void init() {
        LOG.info("初始化 OGNL 数据处理器，规则文件路径: {}", rulesPath);
        loadOgnlRules();
    }

    /**
     * 加载 OGNL 规则
     */
    private void loadOgnlRules() {
        try {
            File file = ResourceUtils.getFile(rulesPath);
            List<String> lines = Files.readAllLines(file.toPath());

            for (String line : lines) {
                if (line.trim().isEmpty() || line.trim().startsWith("#")) {
                    continue; // Skip empty lines and comments
                }

                String[] parts = line.split("=", 2);
                if (parts.length == 2) {
                    String key = parts[0].trim();
                    String expression = parts[1].trim();
                    ognlExpressions.put(key, Ognl.parseExpression(expression));
                    LOG.debug("加载 OGNL 规则: {} = {}", key, expression);
                } else {
                    LOG.warn("忽略无效的规则行: {}", line);
                }
            }

            LOG.info("成功加载 {} 条 OGNL 规则", ognlExpressions.size());
        } catch (IOException e) {
            LOG.error("加载 OGNL 规则文件失败", e);
        } catch (OgnlException e) {
            LOG.error("解析 OGNL 表达式失败", e);
        }
    }

    @Override
    public void process(CollectedData data) throws Exception {
        LOG.debug("开始处理数据, ID: {}", data.getId());

        try {
            HashMap<String, Object> inputData = data.getData();
            OgnlContext context = (OgnlContext) Ognl.createDefaultContext(inputData);

            for (Map.Entry<String, Object> entry : ognlExpressions.entrySet()) {
                String key = entry.getKey();
                Object expression = entry.getValue();

                try {
                    Object result = Ognl.getValue(expression, context, context.getRoot());
                    inputData.put(key, result);
                    LOG.debug("OGNL 处理结果: {} = {}", key, result);
                } catch (OgnlException e) {
                    LOG.error("执行 OGNL 表达式失败, key: {}, expression: {}", key, expression, e);
                    data.setStatus(com.pancm.datacollector.queue.DataStatus.FAILED);
                    throw e;
                }
            }

            data.setStatus(com.pancm.datacollector.queue.DataStatus.PROCESSED);
            LOG.debug("数据处理完成, ID: {}", data.getId());
        } catch (Exception e) {
            LOG.error("数据处理失败, ID: {}", data.getId(), e);
            data.setStatus(com.pancm.datacollector.queue.DataStatus.FAILED);
            throw e;
        }
    }

    @Override
    public ProcessorConfig getConfig() {
        return config;
    }

    @Override
    public void updateConfig(ProcessorConfig config) throws Exception {
        LOG.info("更新处理器配置...");
        this.config = config;
        loadOgnlRules();
        LOG.info("处理器配置更新完成");
    }
} 